
/*数码管的显示是扫描方法显示，扫描间隔由定时器决定（暂为2ms）。在定时器中断处理函数中，每次只驱动1个数码管，下一个中断处理下一个数码管。
定时器ISR，处理的数据是seg_cur.seg[seg_cur.idx].data。所以，只需要更改xxx.seg[idx].data即可。现在没有包装好，很多函数都是直接操作seg_cur.seg[seg_cur.idx].data。
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>


#include "cmsis_os2.h"

#include "stm32l4xx.h"
#include "stm32l4xx_ll_bus.h"
#include "stm32l4xx_ll_gpio.h"
#include "stm32l4xx_ll_tim.h"

#include "bsp.h"
#include "dbgUart.h"
#include "parameter.h"

#include "drv_ch423s.h"



/*定义DISP_ANA模式下小数点的固定位置。
*/
#define DOT_POS_ANA						3



//数码管的8段电平控制。
#ifdef V11
	#define A_ON							LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_15)
	#define A_OFF							LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_15)
#else
#define A_ON							LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_8)
#define A_OFF							LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_8)
#endif
#define B_LED4_STAB_ON					LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_6)
#define B_LED4_STAB_OFF					LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_6)
#define C_LED5_ON						LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_0)
#define C_LED5_OFF						LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_0)
#define D_ON							LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_5)
#define D_OFF							LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_5)
#define E_LED3_ZERO_ON					LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_6)
#define E_LED3_ZERO_OFF					LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_6)
#define F_ON							LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_7)
#define F_OFF							LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_7)
#ifdef V11
	#define G_ON							LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_3)
	#define G_OFF							LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_3)
#else
	#define G_ON							LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_4)
	#define G_OFF							LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_4)
#endif

#define DP_ON							LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_1)
#define DP_OFF							LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_1)

static void seg_sel(uint8_t x);
static void seg_disp(uint8_t data, uint8_t dot);
static void seg_tim_scan_init(uint32_t T);
static void seg_buf1_to_seg(void);
static void seg_sel_none(void);
static void zeros_deal_in_not_neg(char* str);	//非负数字符串前导零的去除。
static void zeros_deal_in_neg(char* str);		//负数字符串前导零的去除。
void BUZ_TMO_Handler(void);
void SCAN_TMO_Handler(void);


enum X{X0= 0,X1,X2,X3,X4,X5,X6};				//选通引脚的枚举类型
enum OWNER{OWN_INT=0,OWN_APP};


/*支持1个数码管显示的元素。
*/
typedef struct _SEG{
	uint8_t data;
	uint8_t hasDot;			//是否显示小数点
	uint8_t disp_mode;		//亮，灭，闪
	uint8_t sta;			//仅在闪模式下有效，0---闪下的灭，其他---闪下的亮。
	uint8_t internal;		//闪模式下的设定时长，当计时cnt到达时，更改sta。
	uint16_t cnt;			//闪模式下的状态计时。
}SEG;

typedef struct _SEG7{
	uint32_t xxx;						//调试时新增，无效果。
	signed char buf_disp_1[8];			//C 6个数码管和3个发光二极管。小数点占1个字节，但不单独显示。buf_disp_1[0]是3个发光二极管状态。
	signed char buf_disp_2[8];			//C 显示缓存。
	SEG seg[7];							//C !!seg[0]对应发光二极管，seg[1]对应左起第1个数据管，seg[2]对应左起第2个数据管...。3个指示灯（发光二极管）的闪，不属于disp_mode的闪（8段全闪），需要更新数据，不是设置状态。
	uint8_t owner;						//C 拥有者：1--应用，0--显示。当为0时，ISR检测到，更新buf_disp_1[]到seg[]。
	uint8_t idx;						//C 扫描显示过程中的中间状态。
	uint16_t cnt;						//闪模式下的状态计时。
	uint8_t internal;					//闪模式下的设定时长，当计时cnt到达时，更改sta。
	uint8_t sta;						//仅在闪模式下有效，0---闪下的灭，其他---闪下的亮。
}SEG7;

static SEG7 seg_cur={.idx= 0};



/*配置按键输入引脚。
*/
void bsp_key_hal(void)
{
	LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA |LL_AHB2_GRP1_PERIPH_GPIOB | LL_AHB2_GRP1_PERIPH_GPIOC);
	/*
	K1	Pin28/PB2	按键ZERO/ESC/■，低有效
	K2	Pin27/PB1	按键OPTION/▲，低有效
	K3	Pin57/PB5	按键MODE/▷，低有效
	K4	Pin56/PB4	按键HOLD/ENTER/●，低有效
	*/
	LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_2,LL_GPIO_PULL_UP);
	LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_2, LL_GPIO_MODE_INPUT);
	
	LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_1,LL_GPIO_PULL_UP);
	LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_1, LL_GPIO_MODE_INPUT);
	
	LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_5,LL_GPIO_PULL_UP);
	LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_5, LL_GPIO_MODE_INPUT);
	
	LL_GPIO_SetPinPull(GPIOB, LL_GPIO_PIN_4,LL_GPIO_PULL_UP);
	LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_4, LL_GPIO_MODE_INPUT);
	
	
	/*隔离IO。
	IN1	Pin37/PC6	当外部有信号时，检测到低电平。
	OUT1	Pin44/PA11	当输出高时，OUTx表现为ON。
	OUT2	Pin45/PA12	当输出高时，OUTx表现为ON。
	*/
	#ifdef WV100
		//WV100有2个IN：IN1--PA4， IN2---PC9。
		LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_4,LL_GPIO_PULL_UP);
		LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_4, LL_GPIO_MODE_INPUT);
		
		LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_9,LL_GPIO_PULL_UP);
		LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_9, LL_GPIO_MODE_INPUT);
	#else
		LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_6,LL_GPIO_PULL_UP);
		LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_6, LL_GPIO_MODE_INPUT);
	#endif
	
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_11,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_11, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_11);	//!!上电默认输出H，即OUTx为OFF。	
	
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_12,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_12, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_12);	//!!上电默认输出H，即OUTx为OFF。
	
	
	/*测试点用PA8（MCO），PC9。
	*/
	#ifndef WV100
		LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_9,LL_GPIO_OUTPUT_PUSHPULL);
		LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_9, LL_GPIO_MODE_OUTPUT);
		LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_9);		//!!上电默认输出H。
	#endif
	
	//PA8 as link with DS28E.
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_8,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_8, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_8);		//!!上电默认输出H，以给单线芯片供电。
	
	/*BLE芯片电源控制引脚：PC2，低有效。
	*/
	LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_2,LL_GPIO_OUTPUT_PUSHPULL);                                          
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_2, LL_GPIO_MODE_OUTPUT);
	BLE_ON;											//!!上电默认输出L，使能BLE。
	
	#ifdef X_IO
	/*初始化变量*/
	for(int i= 0; i< 7; i++){
		seg_cur.buf_disp_1[i]= 0;
		seg_cur.buf_disp_2[i]= 0;
		
		seg_cur.seg[i].disp_mode= SEG_LIGHT;
		seg_cur.seg[i].data= '1';
		seg_cur.seg[i].hasDot= 0;
	}
	seg_cur.seg[1].data= '1';
	seg_cur.seg[2].data= '2';
	seg_cur.seg[3].data= '3';
	seg_cur.seg[4].data= '4';
	seg_cur.seg[5].data= '5';
	seg_cur.seg[6].data= '6';
	
	
	seg_cur.idx= 0;
	seg_cur.owner= OWN_INT;
	#endif
}


/*数码管用到的GPIO:数码管的8段+6个选通引脚
  1个3个发光二极管的选通引脚
*/
void bsp_seg_hal(void)
{
	LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
	LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
	LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
	/*
	A	Pin61/PB8	数码管的A段，低有效
	B	Pin58/PB6	数码管的B段和LED4，低有效
	C	Pin14/PA0	数码管的C段和LED5，低有效
	D	Pin21/PA5	数码管的D段，低有效
	E	Pin22/PA6	数码管的E段和LED3，低有效
	F	Pin59/PB7	数码管的F段，低有效
	G	Pin20/PA4	数码管的G段，低有效
	DP	Pin15/PA1	数码管的DP段，低有效
	(没有bit7 6 5 4 3 2 1 0的对应关系）
	*/
	#ifdef V11
		LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_15,LL_GPIO_OUTPUT_PUSHPULL);
		LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_15, LL_GPIO_MODE_OUTPUT);
		LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_15);
	#else
		LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_8,LL_GPIO_OUTPUT_PUSHPULL);
		LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_8, LL_GPIO_MODE_OUTPUT);
		LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_8);
	#endif
	
	LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_6,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_6, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_6);
	
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_0,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_0, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_0);
	
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_5,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_5, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_5);
	
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_6,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_6, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_6);
	
	LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_7,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_7, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_7);
	
	#ifdef V11
		LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_3,LL_GPIO_OUTPUT_PUSHPULL);
		LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_3, LL_GPIO_MODE_OUTPUT);
		LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_3);
	#else
		LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_4,LL_GPIO_OUTPUT_PUSHPULL);
		LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_4, LL_GPIO_MODE_OUTPUT);
		LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_4);
	#endif
	
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_1,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_1, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_1);
	
	/*
	X1	Pin26/PB0	第1个数码管选通，低有效
	X2	Pin25/PC5	第2个数码管选通，低有效
	X3	Pin24/PC4	第3个数码管选通，低有效
	X4	Pin9/PC1	第4个数码管选通，低有效
	X5	Pin3/PC14	第5个数码管选通，低有效
	X6	Pin2/PC13	第6个数码管选通，低有效
	X0	Pin23/PA7	3个发光二极管的选通，低有效
	*/
	LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_0,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_0, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_0);	
	
	LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_5,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_5, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_5);	
	
	LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_4,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_4, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_4);	

	LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_1,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_1, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_1);
	
	LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_14,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_14, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_14);

	LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_13,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_13, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_13);
	
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_7,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_7, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_7);	
	
	
	/*隔离IO。
	IN1	Pin37/PC6	当外部有信号时，检测到低电平。
	OUT1	Pin44/PA11	当输出高时，OUTx表现为ON。
	OUT2	Pin45/PA12	当输出高时，OUTx表现为ON。
	*/
	LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_6,LL_GPIO_PULL_UP);
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_6, LL_GPIO_MODE_INPUT);
	
	
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_11,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_11, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_11);	//!!上电默认输出H，即OUTx为OFF。	
	
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_12,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_12, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_12);	//!!上电默认输出H，即OUTx为OFF。
	
	
	/*测试点用PA8（MCO），PC9。
	*/
	LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_9,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_9, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_9);		//!!上电默认输出H。

	//PA8 as link with DS28E.
	LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_8,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_8, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_8);		//!!上电默认输出H，以给单线芯片供电。
	
	/*BLE芯片电源控制引脚：PC2，低有效。
	*/
	LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_2,LL_GPIO_OUTPUT_PUSHPULL);                                          
	LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_2, LL_GPIO_MODE_OUTPUT);
	LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_2);		//!!上电默认输出L，使能BLE。
	
	
	/*初始化变量*/
	for(int i= 0; i< 7; i++){
		seg_cur.buf_disp_1[i]= 0;
		seg_cur.buf_disp_2[i]= 0;
		
		seg_cur.seg[i].disp_mode= SEG_LIGHT;
		seg_cur.seg[i].data= '1';
		seg_cur.seg[i].hasDot= 0;
	}
	seg_cur.seg[1].data= '1';
	seg_cur.seg[2].data= '2';
	seg_cur.seg[3].data= '3';
	seg_cur.seg[4].data= '4';
	seg_cur.seg[5].data= '5';
	seg_cur.seg[6].data= '6';
	
	
	seg_cur.idx= 0;
	seg_cur.owner= OWN_INT;
	
	seg_tim_scan_init(4-1);	//数码管扫描用定时周期为2ms。	//若为8-6，目测闪。最小取4。QQ实测(N-1)是间隔，不是N。
}



/*驱动一个数码管显示的ASCII和自定义图形（如"-","="等）。
1. 支持ASCII码。
2. 支持自定义图形，>0x80。
如果遇到小数点，需要将小数点和之前的符号放在一起。
*/
static void seg_disp(uint8_t data, uint8_t dot)
{
		A_OFF;
		B_LED4_STAB_OFF;
		C_LED5_OFF;
		D_OFF;
		E_LED3_ZERO_OFF;
		F_OFF;
		G_OFF;
		DP_OFF;
	
		if('0' == data){
			A_ON;
			B_LED4_STAB_ON;
			C_LED5_ON;
			D_ON;
			E_LED3_ZERO_ON;
			F_ON;
		}
		else if('1' == data){
			B_LED4_STAB_ON;
			C_LED5_ON;
		}
		else if('2' == data){	
			//ABGED
			A_ON;
			B_LED4_STAB_ON;
			D_ON;
			E_LED3_ZERO_ON;
			G_ON;	
		}
		else if('3' == data){
			//ABCDG
			A_ON;
			B_LED4_STAB_ON;
			C_LED5_ON;
			D_ON;
			G_ON;	
		}
		else if('4' == data){
			//BCFG
			B_LED4_STAB_ON;
			C_LED5_ON;
			F_ON;
			G_ON;	
		}
		else if('5' == data){
			//ACDFG
			A_ON;
			C_LED5_ON;
			D_ON;
			F_ON;
			G_ON;	
		}
		else if('6' == data){
			//ACDEFG
			A_ON;
			C_LED5_ON;
			D_ON;
			E_LED3_ZERO_ON;
			F_ON;
			G_ON;	
		}
		else if('7' == data){
			//ABC
			A_ON;
			B_LED4_STAB_ON;
			C_LED5_ON;
		}
		else if('8' == data){
			//ABCDEFG
			A_ON;
			B_LED4_STAB_ON;
			C_LED5_ON;
			D_ON;
			E_LED3_ZERO_ON;
			F_ON;
			G_ON;	
		}
		else if('9' == data){
			//ABCDFG
			A_ON;
			B_LED4_STAB_ON;
			C_LED5_ON;
			D_ON;
			F_ON;
			G_ON;	
		}
		else{	//自定义图形（!!但都能对应到ASCII中，以方便操作）。
			if(('a' == data) || ('A' == data)){
				////ABCEFG
				A_ON;
				B_LED4_STAB_ON;
				C_LED5_ON;
				E_LED3_ZERO_ON;
				F_ON;
				G_ON;	
			}
			else if(('b' == data) || ('B' == data)){
				//CDEFG
				C_LED5_ON;
				D_ON;
				E_LED3_ZERO_ON;
				F_ON;
				G_ON;
			} 
			else if('c' == data){
				//DEG
				D_ON;
				E_LED3_ZERO_ON;
				G_ON;
			}
			else if('C' == data){
				//DEFA
				D_ON;
				E_LED3_ZERO_ON;
				F_ON;
				A_ON;
			}
			else if(('d' == data) || ('D' == data)){
				if('d'== data){
					//BCDEG
					B_LED4_STAB_ON;
					C_LED5_ON;
					D_ON;
					E_LED3_ZERO_ON;
					G_ON;
				}
				else{
					
				}
			}
			else if(('e' == data) || ('E' == data)){
				//ADEFG
				A_ON;
				D_ON;
				E_LED3_ZERO_ON;
				F_ON;
				G_ON;
			}
			else if(('f' == data) || ('F' == data)){
				//AEFG
				A_ON;
				E_LED3_ZERO_ON;
				F_ON;
				G_ON;
			}
			else if(('g' == data) || ('G' == data)){	//9
				//ABCDFG
				A_ON;
				B_LED4_STAB_ON;
				C_LED5_ON;
				D_ON;
				F_ON;
				G_ON;
			}
			else if(('h' == data) || ('H' == data)){
				if('h' == data){
					//
					C_LED5_ON;
					E_LED3_ZERO_ON;
					F_ON;
					G_ON;
				}
				else{
					//
					B_LED4_STAB_ON;
					C_LED5_ON;
					E_LED3_ZERO_ON;
					F_ON;
					G_ON;
				}
			}
			else if(('i' == data) || ('I' == data)){
				if('i' == data){
					C_LED5_ON;
				}
				else{
					E_LED3_ZERO_ON;
					F_ON;
				}
			}
			else if(('j' == data) || ('J' == data)){
				//BCD
				B_LED4_STAB_ON;
				C_LED5_ON;
				D_ON;
			}
			else if(('k' == data) || ('K' == data)){
				//无
				E_LED3_ZERO_ON;
				F_ON;
				G_ON;
			}
			else if(('l' == data) || ('L' == data)){
				//DEF
				D_ON;
				E_LED3_ZERO_ON;
				F_ON;
			}
			else if(('m' == data) || ('M' == data)){
				//无
			}
			else if(('n' == data) || ('N' == data)){
				if('n' == data){
					//显示'n'
					C_LED5_ON;
					E_LED3_ZERO_ON;
					G_ON;
				}
				else{
					//显示‘N'
					A_ON;
					B_LED4_STAB_ON;
					C_LED5_ON;
					E_LED3_ZERO_ON;
					F_ON;
				}
			}
			else if(('o' == data) || ('O' == data)){
				if('o' == data){
					//CDEG
					C_LED5_ON;
					D_ON;
					E_LED3_ZERO_ON;
					G_ON;
				}
				else{
					//'O'显示一样：'0'
					A_ON;
					B_LED4_STAB_ON;
					C_LED5_ON;
					D_ON;
					E_LED3_ZERO_ON;
					F_ON;
				}
			}
			else if(('p' == data) || ('P' == data)){
				//无
				A_ON;
				B_LED4_STAB_ON;
				E_LED3_ZERO_ON;
				F_ON;
				G_ON;
			}
			else if(('q' == data) || ('Q' == data)){
				//无
				A_ON;
				B_LED4_STAB_ON;
				C_LED5_ON;
				F_ON;
				G_ON;
			}
			else if(('r' == data) || ('R' == data)){
				//参考DT45的显示：Force
				E_LED3_ZERO_ON;
				G_ON;
			}
			else if(('s' == data) || ('S' == data)){
				//显示等于'5'
				//ACDFG
				A_ON;
				C_LED5_ON;
				D_ON;
				F_ON;
				G_ON;
			}
			else if(('t' == data) || ('T' == data)){
				//无
				//ACDFG
				D_ON;
				E_LED3_ZERO_ON;
				F_ON;
				G_ON;
			}
			else if(('u' == data) || ('U' == data)){
				if('u' == data){
					//CDE
					C_LED5_ON;
					D_ON;
					E_LED3_ZERO_ON;
				}
				else{
					//缺AG
					B_LED4_STAB_ON;
					C_LED5_ON;
					D_ON;
					E_LED3_ZERO_ON;
					F_ON;
				}
			}
			else if(('v' == data) || ('V' == data)){	//和'U'显示一样。
				if('v' == data){
					//CDE
					C_LED5_ON;
					D_ON;
					E_LED3_ZERO_ON;
				}
				else{
					//缺AG
					B_LED4_STAB_ON;
					C_LED5_ON;
					D_ON;
					E_LED3_ZERO_ON;
					F_ON;
				}
			}
			else if(('w' == data) || ('W' == data)){
				//无
			}
			else if(('x' == data) || ('X' == data)){
				//无
			}
			else if(('y' == data) || ('Y' == data)){
				//缺ae
				B_LED4_STAB_ON;
				C_LED5_ON;
				D_ON;
				F_ON;
				G_ON;
			}
			else if(('z' == data) || ('Z' == data)){
				//无
			}
			
			//非英文字符
			else if('-' == data){
				G_ON;	
			}
			else if('=' == data){
				D_ON;
				G_ON;
			}
			else if( ' ' == data){
				//空
			}
			else{
				/*非ASCII码，可能对应发光二级管
				bit0---LED3_ZERO
				bit1---LED4_STAB
				bit2---LED5_HOLD
				*/
				if(data & 0x01){
					E_LED3_ZERO_ON;
				}
				if(data & 0x02)
					B_LED4_STAB_ON;
				if(data & 0x04)
					C_LED5_ON;
				
				//uartS("\n\terr:unknow char");
			}
		}
		
		if(0 != dot){
			DP_ON;
		}
}


/*数码管的显示为动态扫描：共7个选通引脚，扫描一次为4*7ms，即定时器周期为4ms（暂定）
输入参数 T: 定时器周期。
使用TIM7.
a. 当ARPE=1，只在event UEV时更新ARR。
b. The update event is sent when the counter reaches the overflow value and if the UDIS bit equals 0 in the TIMx_CR1 register. 
   The counter counts from 0 to the auto-reload value (contents of the TIMx_ARR register), then restarts from 0 and generates a counter overflow event.
*/
static void seg_tim_scan_init(uint32_t T)
{
	if(0 == T)
		return;
	
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM7);
	
	LL_TIM_SetPrescaler(TIM7, 48000-1);	//分频到1KHz。
	LL_TIM_SetAutoReload(TIM7, T);
	
	LL_TIM_GenerateEvent_UPDATE(TIM7);	//马上更新ARR和PSC。
	
	LL_TIM_ClearFlag_UPDATE(TIM7);
	LL_TIM_EnableIT_UPDATE(TIM7);
	
	LL_TIM_EnableCounter(TIM7);
	
	NVIC_SetPriority(TIM7_IRQn, 7);
	NVIC_EnableIRQ(TIM7_IRQn);
}


/*在TIM7的ISR中，更新数码管。
typedef struct _SEG{
	uint8_t data;
	uint8_t hasDot;				//是否显示小数点
	uint8_t disp_mode;			//亮，灭，闪
	uint8_t internal;			//闪的时长
	uint16_t cnt;				//闪或灭的记时。
}SEG;
*/
void SCAN_TMO_Handler(void)
{
	LL_TIM_ClearFlag_UPDATE(TIM7);
	
	//BUZ_ON;
	
	seg_sel_none();	//seg_sel(seg_cur.idx);
	
	//要显示seg_cur.idx。
	if(SEG_LIGHT == seg_cur.seg[seg_cur.idx].disp_mode){
		//亮
		seg_disp(seg_cur.seg[seg_cur.idx].data, seg_cur.seg[seg_cur.idx].hasDot);
	}
	else if(SEG_FLASH == seg_cur.seg[seg_cur.idx].disp_mode){
		//闪
		if(seg_cur.sta){
			seg_disp(seg_cur.seg[seg_cur.idx].data, seg_cur.seg[seg_cur.idx].hasDot);
			//uartS("+");
		}
		else{
			seg_disp(' ', 0);	//什么都不显示
			//uartS("-");
		}
	}
	else{ //灭
		seg_disp(' ', 0);		//什么都不显示
	}
	
	seg_sel(seg_cur.idx);		//全灭 ->更新 ->选中，以解决数码管暗闪现象。
	
	
	seg_cur.idx++;
	seg_cur.idx%= 7;

	
	//统一计数，不在单个计数。（暂停）
	if(0 == seg_cur.idx){
		seg_cur.cnt++;
		if(seg_cur.cnt> seg_cur.internal){
			seg_cur.cnt= 0;
			if(seg_cur.sta)
				seg_cur.sta= 0;
			else
				seg_cur.sta= 1;
		}	
	}
	
	//BUZ_OFF;
}


/*将mv值更新到显示缓冲区。
输入参数 mv  : 带显示的有符号数
输入参数 sta3: 随mv来的稳定状态（以驱动STAB灯）
*/
void seg_mv_to_seg(int32_t mv, uint32_t sta3)
{
	//处理数码管显示.seg[1]~seg[6]。
	char str[7];
	if(mv> 999999){
		memcpy(str, "   oFL", 6);
		sta3= 0;	//超限认定为不稳。
	}	
	else
		sprintf(str, "%6d", mv);
	
	
	for(uint32_t i= 0; i< 6; i++)
		seg_cur.seg[i+1].data= str[i];
	
	
	//STAB指示灯
	if(sta3 & BIT_MASK_STAB)
		seg_cur.seg[0].data= 0x02;	//亮
	else
		seg_cur.seg[0].data= 0;		//灭
}



/*暂未实现
*/
void seg_analog_to_seg(int32_t weight, uint32_t sta3){

}



/*将显示值更新到显示缓冲区。
输入参数 weight: 带显示的有符号数
输入参数   sta3: LED_ZERO_BIT,LED_STAB_BIT,LED_HOLD_BIT的位段组合。
*/
void seg_wt_to_seg(int32_t weight, uint32_t sta_led)
{
	//准备：根据显示分度值(eind= cal_ctx.div)。
	char str[16];
//	uint32_t sta;
	

	//判断是否上、下溢出：（依据是当前显示分度值和JJG 649-2016）
	if(weight> (fs_max+ 0)){
		strcpy(str, "   oFL");
		goto L_DISP;
	}
	else{
		if(weight< -99999){
			strcpy(str, "  -OFL");
			goto L_DISP;
		}
		if(weight< (-1*fs_max)){
			strcpy(str, "  -oFL");
			goto L_DISP;
		}
	}

	double wt_double;
	wt_double= weight;
	
	if(0 == para_xxx.pt_pos_idx){
		//"012345"->"012345" 不变
		sprintf(str, "%06d", weight);		
	}
	else if(1 == para_xxx.pt_pos_idx){
		wt_double/= 10;
		sprintf(str, "%.1f", wt_double);
	}
	else if(2 == para_xxx.pt_pos_idx){
		wt_double/= 100;
		sprintf(str, "%.2f", wt_double);
	}
	else if(3 == para_xxx.pt_pos_idx){
		wt_double/= 1000;
		sprintf(str, "%.3f", wt_double);
	}
	else if(4 == para_xxx.pt_pos_idx){
		wt_double/= 10000;
		sprintf(str, "%.4f", wt_double);
	}
	else{
		sprintf(str, "%06d", weight);
	}



	if(6< strlen(str)){
		strcpy(str, "   OFL");
		uartS("\n$err:weight long");
		goto L_DISP;
	}
//	else if(strlen(str)< 6){
//		strcpy(str, "   Err");
//		uartS("\n$err:weight short");
//		
//		return;
//	}

//	//字符串长度=6。
//	/*1. 根据当前小数位数（cal_ctx.pt_num），添加小数点。
//	  2. 去掉前导0，如00.012->0.012。
//	*/
//	if(0 == para_xxx.pt_pos_idx){
//		//"012345"->"012345" 不变	
//	}
//	else if(1 == para_xxx.pt_pos_idx){
//		//"012345"->"01234.5"
//		str[7]= '\n';
//		str[6]= str[5];
//		str[5]= '.';	
//	}
//	else if(2 == para_xxx.pt_pos_idx){
//		//"012345"->"0123.45"
//		str[7]= '\n';
//		str[6]= str[5];
//		str[5]= str[4];
//		str[4]= '.';
//	}
//	else if(3 == para_xxx.pt_pos_idx){
//		//"012345"->"012.345"
//		str[7]= '\n';
//		str[6]= str[5];
//		str[5]= str[4];
//		str[4]= str[3];
//		str[3]= '.';
//	}
//	else if(4 == para_xxx.pt_pos_idx){
//		//"012345"->"01.2345"
//		str[7]= '\n';
//		str[6]= str[5];
//		str[5]= str[4];
//		str[4]= str[3];
//		str[3]= str[2];
//		str[2]= '.';
//	}
//	else{
//		uartS("\err:pt_num");
//	}
//	
//	//TODO删除前导0。
//	zeros_deal_in_not_neg(str);


L_DISP:	
//	sta= 0;
//	if(sta3 & BIT_MASK_STAB)
//		sta|= LED_STAB_BIT;
//	
//	if(sta3 & BIT_MASK_ZERO)
//		sta|= LED_ZERO_BIT;
	
	
	
	//str是靠右显示的。
	x_disp_now(str, sta_led, LED_STAB_BIT | LED_ZERO_BIT | LED_HOLD_BIT); 	//直接显示HOLD指示灯。	
	
//	//seg_cur.seg[0].data对应前面板的3个指示灯。
//	if(sta3 & BIT_MASK_STAB)
//		seg_cur.seg[0].data|= 0x02;		//稳定灯亮
//	else
//		seg_cur.seg[0].data&= ~0x02;	//稳定灯灭

//	if(sta3 & BIT_MASK_ZERO)
//		seg_cur.seg[0].data|= 0x01;		//置零灯亮
//	else
//		seg_cur.seg[0].data&= ~0x01;	//置零灯灭	

//	if(sta3 & BIT_MASK_HOLD)		
//		seg_cur.seg[0].data|= 0x04;		//HOLD灯亮
//	else
//		seg_cur.seg[0].data&= ~0x04;	//HOLD灯灭

//	
//	//处理数码管显示.seg[1]~seg[6]。
//	char str[16];
//	if(weight> fs_max){
//		memcpy(str, "   oFL", 6);
//		
//		for(uint32_t i= 0; i< 6; i++)
//			seg_cur.seg[i+1].data= str[i];
//		
//		//清除所有小数点
//		for(int i= 1; i<= 6; i++)
//			set_one_seg_point(i, 0);
//		
//		return;
//	}
//	else if(weight< (-1*fs_max)){
//		memcpy(str, "  -oFL", 6);
//		
//		for(uint32_t i= 0; i< 6; i++)
//			seg_cur.seg[i+1].data= str[i];
//		
//		//清除所有小数点
//		for(int i= 1; i<= 6; i++)
//			set_one_seg_point(i, 0);	
//		
//		return;
//	}
//	
//	
//	if(0<= weight){
//		//非负数
//		sprintf(str, "%06d", weight);
//		zeros_deal_in_not_neg(str);			//根据小数点位置，剔除前导0。
//	}
//	else{
//		//负数（QQ有正的六位数"123456"，负数只能显示"-99999"。
//		if(weight<-99999)
//			weight= -99999;
//		
//		sprintf(str, "%06d", -1*weight);
//		zeros_deal_in_neg(str);				//根据小数点位置，剔除前导0。
//	}

//	for(uint32_t i= 0; i< 6; i++)
//		seg_cur.seg[i+1].data= str[i];
//	
//	
//	/*处理小数点：
//	1. 添加小数点。
//	2. 判断小数点所在位及其后的位的seg[].data是否等于' '（空），如果等于，写入'0'。
//	*/
//	//清除所有小数点
//	for(int i= 1; i<= 6; i++)
//		set_one_seg_point(i, 0);
//	
//	if(0 != para_xxx.pt_pos_idx){
//		//添加小数点
//		uint16_t i= 6- para_xxx.pt_pos_idx;		//由参数中的小数点位置决定了数码管序号[1,6]。例如数据为123，小数点位置为3，则应显示：0.123
//		
//		if((i< 1) || (6< i)){
//			i= 6;
//			uartS("\nerr dot");
//		}
//		
//		if(' ' == seg_cur.seg[i].data){
//			set_one_seg(i, '0', 1);
//		}
//		else
//			set_one_seg_point(i, 1);
//		
//		for(;i< 7; i++){	//是否还有'0'需要补充。
//			if(' ' == seg_cur.seg[i].data)
//				set_one_seg(i, '0', 0);
//		}
//	}
}



/*从DISP_NORM到DISP_ANA模式下，对seg的处理。
*/
void seg_set_norm_to_ana(void)
{
	//nothing.
}

/*将显示值更新到显示缓冲区，这时是模拟量显示模式
输入参数 weight  : 带显示的有符号数
输入参数 sta3: 随wt来的4种状态（以驱动STAB灯）
情景1：0~5V对应0~fs_max，模拟量的0~5V对应称重值的0~最大量程。
情景2：0~10V对应0~fs_max，模拟量的0~10V对应称重值的0~最大量程。
情景3：4~20mA对应0~fs_max，模拟量的4~20mA对应称重值的0~最大量程。
情景4：0~20mA对应0~fs_max，模拟量的0~20mA对应称重值的0~最大量程。
情景5：0~24mA对应0~fs_max，模拟量的0~24mA对应称重值的0~最大量程。
0	电流输出4-20
1	电流输出0-20
2	电流0-24
3	电压0-5
4	电压0-10
5	电压-5-5
6	电压-10-10
7	自定义I_out，暂未实现
8	自定义V_out，暂未实现
*/
void seg_wt_to_seg_in_ana(int32_t weight, uint32_t sta3)
{
	char str[7];
	uint32_t sta;
	
	
//	if(sta3 & BIT_MASK_STAB)
//		seg_cur.seg[0].data|= 0x02;
//	else
//		seg_cur.seg[0].data&= ~0x02;

//	if(sta3 & BIT_MASK_ZERO)
//		seg_cur.seg[0].data|= 0x01;
//	else
//		seg_cur.seg[0].data&= ~0x01;	
	
	
	int64_t y;	//防止计算过程溢出（y=16000*weight）。
	
	if(weight> fs_max)
		weight= fs_max;
	
	if(0 == strcmp(ITEM_ANA_4_20_STR, _tbl_ana_out[para_self.ana_out_idx])){	//0	电流输出4-20
		/*称重值0 -->4.000
		  称重值fs_max -->20.000
		*/
		if(0>= weight){
			y= 4000;	//归零不是0，是基本的4000。
		}
		else{			
			y= 16000*weight;
			y/= fs_max;
			y+= 4000;
		}
		
		sprintf(str, "A%05d", (int32_t)y);	//以'A'开头。
		

		
//		//处理数码管显示.seg[1]~seg[6]。
//		for(uint32_t i= 0; i< 6; i++)
//			seg_cur.seg[i+2].data= str[i];
//		//seg_cur.seg[0]无作用。
//		seg_cur.seg[1].data= 'A';
//		if('0' == seg_cur.seg[2].data)
//			seg_cur.seg[2].data= ' ';	//09.000时，不显示最左的'0'。
//		
//		set_one_seg_point(DOT_POS_ANA, 1);	//左起第2个数码管带小数点。
	}
	else if(0 == strcmp(ITEM_ANA_0_20_STR, _tbl_ana_out[para_self.ana_out_idx])){	//1	电流输出0-20
		if(0>= weight){
			y= 0;
		}
		else{			
			y= 20000*weight;
			y/= fs_max;
		}
		sprintf(str, "A%05d", (int32_t)y);
		
//		//处理数码管显示.seg[1]~seg[6]。
//		for(uint32_t i= 0; i< 6; i++)
//			seg_cur.seg[i+2].data= str[i];
//		//seg_cur.seg[0]无作用。
//		seg_cur.seg[1].data= 'A';
//		if('0' == seg_cur.seg[2].data)
//			seg_cur.seg[2].data= ' ';	//09.000时，不显示最左的'0'。
//		
//		set_one_seg_point(DOT_POS_ANA, 1);	//左起第2个数码管带小数点。
	}
	else if(0 == strcmp(ITEM_ANA_0_24_STR, _tbl_ana_out[para_self.ana_out_idx])){	//2	电流0-24
		if(0>= weight){
			y= 0;
		}
		else{			
			y= 24000*weight;
			y/= fs_max;
		}
		sprintf(str, "A%05d", (int32_t)y);
		
//		//处理数码管显示.seg[1]~seg[6]。
//		for(uint32_t i= 0; i< 6; i++)
//			seg_cur.seg[i+2].data= str[i];
//		//seg_cur.seg[0]无作用。
//		seg_cur.seg[1].data= 'A';
//		if('0' == seg_cur.seg[2].data)
//			seg_cur.seg[2].data= ' ';	//09.000时，不显示最左的'0'。
//		
//		set_one_seg_point(DOT_POS_ANA, 1);	//左起第2个数码管带小数点。	
	}	
	else if(0 == strcmp(ITEM_ANA_0_5_STR, _tbl_ana_out[para_self.ana_out_idx])){	//3	电压0-5
		if(0>= weight){
			y= 0;
		}
		else{			
			y= 5000*weight;
			y/= fs_max;
		}
		sprintf(str, "A %04d", (int32_t)y);
		
//		//处理数码管显示.seg[1]~seg[6]。
//		for(uint32_t i= 0; i< 6; i++)
//			seg_cur.seg[i+3].data= str[i];	//.seg[1]对应左起第1个数码管。
//		//seg_cur.seg[0]无作用。
//		seg_cur.seg[1].data= 'A';
//		seg_cur.seg[2].data= ' ';
//		
//		set_one_seg_point(DOT_POS_ANA, 1);	//左起第2个数码管带小数点。	
	}	
	else if(0 == strcmp(ITEM_ANA_0_10_STR, _tbl_ana_out[para_self.ana_out_idx])){	//4	电压0-10
		if(0>= weight){
			y= 0;
		}
		else{
			y= 10000*weight;
			y/= fs_max;
		}
		sprintf(str, "A%05d", (int32_t)y);
		
//		//处理数码管显示.seg[1]~seg[6]。
//		for(uint32_t i= 0; i< 6; i++)
//			seg_cur.seg[i+2].data= str[i];
//		//seg_cur.seg[0]无作用。
//		seg_cur.seg[1].data= 'A';
//		if('0' == seg_cur.seg[2].data)
//			seg_cur.seg[2].data= ' ';	//09.000时，不显示最左的'0'。
//		
//		set_one_seg_point(DOT_POS_ANA, 1);	//左起第2个数码管带小数点。	
	}
	else if(0 == strcmp(ITEM_ANA_5_5_STR, _tbl_ana_out[para_self.ana_out_idx])){	//5	电压-5-5，因硬件不支持，所以等效电压0-5。
		if(0>= weight){
			y= 0;
		}
		else{			
			y= 5000*weight;
			y/= fs_max;
		}
		sprintf(str, "A%05d", (int32_t)y);
		
//		//处理数码管显示.seg[1]~seg[6]。
//		for(uint32_t i= 0; i< 6; i++)
//			seg_cur.seg[i+3].data= str[i];	//.seg[1]对应左起第1个数码管。
//		//seg_cur.seg[0]无作用。
//		seg_cur.seg[1].data= 'A';
//		seg_cur.seg[2].data= ' ';
//		
//		set_one_seg_point(DOT_POS_ANA, 1);	//左起第2个数码管带小数点。		
	}	
	else if(0 == strcmp(ITEM_ANA_10_10_STR, _tbl_ana_out[para_self.ana_out_idx])){	//6	电压-10-10，因硬件不支持，所以等效电压0-10。
		if(0>= weight){
			y= 0;
		}
		else{
			y= 10000*weight;
			y/= fs_max;
		}
		sprintf(str, "A%05d", (int32_t)y);
		
//		//处理数码管显示.seg[1]~seg[6]。
//		for(uint32_t i= 0; i< 6; i++)
//			seg_cur.seg[i+2].data= str[i];
//		//seg_cur.seg[0]无作用。
//		seg_cur.seg[1].data= 'A';
//		if('0' == seg_cur.seg[2].data)
//			seg_cur.seg[2].data= ' ';	//09.000时，不显示最左的'0'。
//		
//		set_one_seg_point(DOT_POS_ANA, 1);	//左起第2个数码管带小数点。	
	}
	else{
		uartS("\n\t\terr:unknown ana mode");
	}
	
	
	//显示到数码管和指示灯。
	sta= 0;
	if(sta3 & BIT_MASK_STAB)
		sta|= LED_STAB_BIT;

	if(sta3 & BIT_MASK_ZERO)
		sta|= LED_ZERO_BIT;

	//str是靠右显示的。
	x_disp_now(str, sta, LED_STAB_BIT | LED_ZERO_BIT | LED_HOLD_BIT); 
	x_seg_set_point(PT_L_3, 1);		//小数点固定在坐起第3个数码管，即“A02.456”。
}



/*从DISP_ANA到DISP_NORM模式下，对seg的处理。
*/
void seg_set_ana_to_norm(void)
{
	set_one_seg_point(DOT_POS_ANA, 0);	//左起第2个数码管带小数点。
}



/*更新SEG结构体的显示内容（只包含6个数码管）。
不处理面板3个指示灯状态。
*/
void seg_updata(char* p)
{
#ifdef DT45
	for(int i= 0; i< 7; i++)
		seg_cur.buf_disp_1[i+1]= p[i];
	
	seg_buf1_to_seg();
#endif
	
#ifdef X_CH423S
	x_disp_now(p, 0, LED_NONE);		//-1: 不更改9个LED状态。LED_BAT_BIT
#endif	
}



/*用于测试模式下的全闪控制（含3个发光二极管）。
!!直接修改seg_cur.seg[]。
*/
void seg_flash(uint32_t en)
{
	if(en){
		for(int i=0; i<7; i++){
			seg_cur.seg[i].disp_mode= SEG_FLASH;
//			seg_cur.seg[i].cnt= 0;
//			seg_cur.seg[i].internal= 25;
			seg_cur.cnt= 0;
			seg_cur.internal= TMO_FLASH;	//25*14ms。
		}
	}
	else{
		for(int i=0; i<7; i++){
			seg_cur.seg[i].disp_mode= SEG_LIGHT;
		}
	}
}



/*用于测试模式下的全闪控制（含3个发光二极管）。
!!直接修改seg_cur.seg[]。
*/
void seg_flash_all(uint32_t en)
{	
	if(en){
		for(int i=0; i<7; i++){
			seg_cur.seg[i].disp_mode= SEG_FLASH;
//			seg_cur.seg[i].cnt= 0;
//			seg_cur.seg[i].internal= 25;
			seg_cur.cnt= 0;
			seg_cur.internal= TMO_FLASH;	//25*14ms。
		}
	}
	else{
		for(int i=0; i<7; i++){
			seg_cur.seg[i].disp_mode= SEG_LIGHT;
		}
	}
}



/*直接修改某一个数码管的显示内容。
输入参数 idx:待设置的索引，[0,6]。
输入参数 ch: 待显示的值：ASCII码或其他（其他值适用于3个发光二极管）
输入参数 hasDot: 是否带小数点。0---不带，其他---带。
!!直接修改seg_cur.seg[]。
*/
void set_one_seg(uint32_t idx, uint8_t ch, uint8_t hasDot)
{
	if(6< idx)
		return;
	
	seg_cur.seg[idx].data= ch;
	seg_cur.seg[idx].hasDot= hasDot;
}



/*直接修改某一个数码管的显示模式。
输入参数 idx:待设置的索引，[0,6]。
输入参数 ch: 待显示的值：ASCII码或其他（其他值适用于3个发光二极管）
输入参数 hasDot: 是否带小数点。0---不带，其他---带。
!!直接修改seg_cur.seg[]。
分别对不同的数码管设置，闪烁不一定同步---已解决，统一计数即可。
*/
void set_one_seg_flash(uint32_t idx, uint8_t mode)
{
	if(6< idx)
		return;
	
	seg_cur.seg[idx].disp_mode= mode;
	//seg_cur.seg[idx].internal= 25;
	
	seg_cur.cnt= 0;
	seg_cur.internal= 25;	
}



/*直接修改某一个数码管的是否带小数点。
输入参数 idx:待设置的索引，[1,6]。
输入参数 hasDot: 是否带小数点。0---不带，其他---带。
!!直接修改seg_cur.seg[]。
*/
void set_one_seg_point(uint32_t idx, uint8_t hasDot)
{
	if(6< idx)
		return;
	
	seg_cur.seg[idx].hasDot= hasDot;
}



/*将指定的数码管的显示值为空（即正号）或'-'（即负号）。
*/
void sign_one_seg(uint32_t idx)
{
	if((0 == idx) || (6< idx))
		return;
	
	if('0'== seg_cur.seg[idx].data)
		seg_cur.seg[idx].data='-';
	else
		seg_cur.seg[idx].data='0';
}


/*将指定的数码管的显示值加1，如显示8，执行后显示9。若超过9，返回0。
*/
void inc_one_seg(uint32_t idx)
{
	#ifdef X_CH423S
	/*使用全局变量int_menu，不使用输入参数idx，而是使用int_menu.pos，以更新int_menu.val。
	如果允许负值，最高位可以在'-','0'...'9'遍历。
	在最高位的条件：int_menu.dig+ int_menu.pos==6。
	*/
	
	
	
	#else	
	if((0 == idx) || (6< idx))
		return;
	
	if(seg_cur.seg[idx].data <'0')
		seg_cur.seg[idx].data='0'-1;
	
	if('9'< (seg_cur.seg[idx].data+ 1))
		seg_cur.seg[idx].data='0';
	else
		seg_cur.seg[idx].data++;
	#endif
}


/*将指定的数码管的显示值加1，如显示8，执行后显示9。若超过9，返回0。
*/
void dec_one_seg(uint32_t idx)
{
	if((0 == idx) || (6< idx))
		return;
	
	if(seg_cur.seg[idx].data == '0')
		seg_cur.seg[idx].data='9';
	else
		seg_cur.seg[idx].data--;
}


/*拷贝当前显示字符到指定变量，实现临时保存当前显示值，以供后用。
不想暴露seg_cur变量。
!!目前只拷贝[1~6]，没有[0]。[0]是3个发光二极管的状态。
*/
void seg_copy_to_tmp(char* p)
{
	for(int i=1; i< 7; i++)
		p[i]= seg_cur.seg[i].data;
}



/*拷贝指定变量到当前显示字符。一般和seg_copy_to_tmp()配对使用。
不想暴露seg_cur变量。
!!目前只拷贝[1~6]，没有[0]。[0]是3个发光二极管的状态。
*/
void seg_copy_from_tmp(char* p)
{
	for(int i=1; i< 7; i++)
		seg_cur.seg[i].data= p[i];
}


/*返回STAB指示灯状态（有效或无效）。
*/
uint32_t seg_stab_sta(void)
{
	return (seg_cur.seg[0].data&0x02) ? 1:0;
}

/*将seg_cur.buf_disp_1[]格式化到seg_cur.seg[]。主要是整理小数点。
说明：
1. seg_cur.buf_disp_1[0]是发光二极管的状态。
2. seg_cur.buf_disp_[1]及之后，为字符串形式，不含小数点。
3. 小数点根据参数中的小数点位置添加。
*/
static void seg_buf1_to_seg(void)
{
	//处理发光二极管状态
	seg_cur.seg[0].data = seg_cur.buf_disp_1[0];	//
//	
//	//处理_disp_1[1]及其之后
//	char str[7];
//	
//	if(seg_cur.buf_disp_1[0] & LED3_ZERO_MASK){
//		seg_cur.seg[0] |= 
//	}
	/*考虑小数点的一种情况：将N+1处小数点写入N。
	如"1.23" ->
	seg_cur.seg[1].data= '1'; seg_cur.seg[1].hasDot= 1;
	seg_cur.seg[2].data= '2'; seg_cur.seg[2].hasDot= 0;
	seg_cur.seg[3].data= '3'; seg_cur.seg[3].hasDot= 0;
	*/
	uint8_t k= 1;
	
	for(int i=1; i<7; i++){	//6个数码管
		seg_cur.seg[i].data= seg_cur.buf_disp_1[k];
		seg_cur.seg[i].hasDot= 0;
		
		if('.' == seg_cur.buf_disp_1[k+1]){
			seg_cur.seg[i].hasDot= 1;
			k++;
		}
			
		k++;
	}	
}



/*
*/
static void seg_sel_none(void)
{
	LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_0);
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_5);	
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_4);	
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_1);
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_14);
	LL_GPIO_SetOutputPin(GPIOC, LL_GPIO_PIN_13);
	LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_7);	
}

/*选通7个引脚中的1个。
*/
static void seg_sel(uint8_t x)
{
	seg_sel_none();
	
	if(X1 == x){
		LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_0);
	}
	else if(X2 == x){
		LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_5);	
	}
	else if(X3 == x){
		LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_4);	
	}
	else if(X4 == x){
		LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_1);
	}
	else if(X5 == x){
		LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_14);
	}
	else if(X6 == x){
		LL_GPIO_ResetOutputPin(GPIOC, LL_GPIO_PIN_13);
	}
	else{	//X0---3个发光二极管。
		LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_7);	
	}
}


/*获取隔离输入的所有引脚状态。1--有效，0--无效。
*/
uint32_t io_get(void)
{
	return LL_GPIO_IsInputPinSet(GPIOC, LL_GPIO_PIN_6)?0:1;
}


/*配置蜂鸣器驱动引脚
BUZ	Pin55/PB3	高有效
*/
void bsp_buz_hal(void)
{
	LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
	
	//LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_3, LL_GPIO_SPEED_FREQ_VERY_HIGH);
	LL_GPIO_SetPinSpeed(GPIOB, LL_GPIO_PIN_3, LL_GPIO_SPEED_FREQ_LOW);
	LL_GPIO_SetPinOutputType(GPIOB, LL_GPIO_PIN_3,LL_GPIO_OUTPUT_PUSHPULL);
	LL_GPIO_SetPinMode(GPIOB, LL_GPIO_PIN_3, LL_GPIO_MODE_OUTPUT);
	
	LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_3);
}



static void buz_tim_start(uint32_t tenms)
{
	if(0 == tenms)
		return;
	
	LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM6);
	
	LL_TIM_DisableCounter(TIM6);
	NVIC_DisableIRQ(TIM6_IRQn);
	
	LL_TIM_SetPrescaler(TIM6, 48000-1);	//分频到1KHz。
	LL_TIM_SetAutoReload(TIM6, tenms);
	
	//LL_TIM_GenerateEvent_UPDATE(TIM6);	//马上更新ARR和PSC。  //QQ!!为什么要去掉这条语句。不注释，定时器计时不对，根因待查。
	LL_TIM_SetCounter(TIM6, 0);
	
	LL_TIM_ClearFlag_UPDATE(TIM6);
	LL_TIM_EnableIT_UPDATE(TIM6);
	
	LL_TIM_EnableCounter(TIM6);
	
	NVIC_SetPriority(TIM6_IRQn, 6);
	NVIC_EnableIRQ(TIM6_IRQn);
}



/*蜂鸣器定时器ISR。
*/
void BUZ_TMO_Handler(void)
{
	LL_TIM_ClearFlag_UPDATE(TIM6);
	
	LL_TIM_DisableCounter(TIM6);
	NVIC_DisableIRQ(TIM6_IRQn);
	//LL_TIM_SetCounter(TIM6, 0);
	
	BUZ_OFF;
}



/*开启蜂鸣器，开启时长由参数tenms指定(10ms/单位）。
由定时器决定时长。
*/
void buz_beep(uint32_t tenms)
{
	if(dbg_sw & DBG_BUZ){
		BUZ_ON;
		buz_tim_start(tenms);
	}		
}


void buz_on(void)
{
	BUZ_ON;
}

void buz_stop(void)
{
	BUZ_OFF;
}


void seg_disp_8_dot(void)
{
	/*初始化变量*/
	for(int i= 0; i< 7; i++){
		seg_cur.buf_disp_1[i]= 0;
		seg_cur.buf_disp_2[i]= 0;
		
		seg_cur.seg[i].disp_mode= SEG_LIGHT;
		seg_cur.seg[i].data= '8';
		seg_cur.seg[i].hasDot= 1;
	}
}


void seg_disp_blank(void)
{
	/*初始化变量*/
	for(int i= 0; i< 7; i++){
		seg_cur.buf_disp_1[i]= 0;
		seg_cur.buf_disp_2[i]= 0;
		
		seg_cur.seg[i].disp_mode= SEG_LIGHT;
		seg_cur.seg[i].data= ' ';
		seg_cur.seg[i].hasDot= 0;
	}
}


/*显示logo:"0ForcE"。
*/
void seg_disp_logo(void)
{
	/*初始化变量*/
	for(int i= 0; i< 7; i++){
		seg_cur.buf_disp_1[i]= 0;
		seg_cur.buf_disp_2[i]= 0;
		
		seg_cur.seg[i].disp_mode= SEG_LIGHT;
		seg_cur.seg[i].data= ' ';
		seg_cur.seg[i].hasDot= 0;
	}
	seg_cur.seg[1].data= '0';
	seg_cur.seg[2].data= 'F';
	seg_cur.seg[3].data= 'o';
	seg_cur.seg[4].data= 'r';
	seg_cur.seg[5].data= 'c';
	seg_cur.seg[6].data= 'E';
}



/*非负数转换的字符串按小数点位置处理前导0。
*/
static void zeros_deal_in_not_neg(char* str)
{
	//根据小数点位置，剔除前导0。小数点位置（0：0位，1：1位，2：2位，3：3位，4：4位）

	if(0 == strcmp(ITEM_pt_0, _tbl_pt_pos[para_xxx.pt_pos_idx])){
		//判断并退出前面的5个零。如"000004"->"     4"
		if('0' == str[0]){
			str[0]= ' ';
			
			if('0' == str[1]){
				str[1]= ' ';
				
				if('0' == str[2]){
					str[2]= ' ';
					
					if('0' == str[3]){
						str[3]= ' ';
						
						if('0' == str[4]){
							str[4]= ' ';
						}
					}
				}
			}
		}
	}
	else if( 0 == strcmp(ITEM_pt_1, _tbl_pt_pos[para_xxx.pt_pos_idx])){
		//判断并退出前面的4个零。如"00000.4"->"    0.4"
		if('0' == str[0]){
			str[0]= ' ';
			
			if('0' == str[1]){
				str[1]= ' ';
				
				if('0' == str[2]){
					str[2]= ' ';
					
					if('0' == str[3]){
						str[3]= ' ';
					}
				}
			}
		}
	}
	else if( 0 == strcmp(ITEM_pt_2, _tbl_pt_pos[para_xxx.pt_pos_idx])){
		//判断并退出前面的3个零。如"0000.04"->"   0.04"
		if('0' == str[0]){
			str[0]= ' ';
			
			if('0' == str[1]){
				str[1]= ' ';
				
				if('0' == str[2]){
					str[2]= ' ';
				}
			}
		}
	}
	else if( 0 == strcmp(ITEM_pt_3, _tbl_pt_pos[para_xxx.pt_pos_idx])){
		//判断并退出前面的2个零。如"000.004"->"   0.004"
		if('0' == str[0]){
			str[0]= ' ';
			
			if('0' == str[1]){
				str[1]= ' ';
			}
		}
	}
	else if( 0 == strcmp(ITEM_pt_4, _tbl_pt_pos[para_xxx.pt_pos_idx])){
		//判断并退出前面的`个零。如"00.0004"->"  0.0004"
		if('0' == str[0]){
			str[0]= ' ';
		}
	}
	else{ 
		//do nothing.
	}	
}



/*负数转换的字符串按小数点位置处理前导0。
*/
static void zeros_deal_in_neg(char* str)
{
	//根据小数点位置，剔除前导0。小数点位置（0：0位，1：1位，2：2位，3：3位，4：4位）
	if(0 == para_xxx.pt_pos_idx){
		//判断并退出前面的5个零。如"-00004"->"     4"
		if('0' == str[0]){
			str[0]= ' ';
			
			if('0' == str[1]){
				str[1]= ' ';
				
				if('0' == str[2]){
					str[2]= ' ';
					
					if('0' == str[3]){
						str[3]= ' ';
						
						if('0' == str[4]){
							str[4]= ' ';
						}
					}
				}
			}
		}
	}
	else if( 1 == para_xxx.pt_pos_idx){
		//判断并退出前面的4个零。如"00000.4"->"    0.4"
		if('0' == str[0]){
			str[0]= ' ';
			
			if('0' == str[1]){
				str[1]= ' ';
				
				if('0' == str[2]){
					str[2]= ' ';
					
					if('0' == str[3]){
						str[3]= ' ';
					}
				}
			}
		}
	}
	else if( 2 == para_xxx.pt_pos_idx){
		//判断并退出前面的3个零。如"0000.04"->"   0.04"
		if('0' == str[0]){
			str[0]= ' ';
			
			if('0' == str[1]){
				str[1]= ' ';
				
				if('0' == str[2]){
					str[2]= ' ';
				}
			}
		}
	}
	else if( 3 == para_xxx.pt_pos_idx){
		//判断并退出前面的2个零。如"000.004"->"   0.004"
		if('0' == str[0]){
			str[0]= ' ';
			
			if('0' == str[1]){
				str[1]= ' ';
			}
		}
	}
	else if( 4 == para_xxx.pt_pos_idx){
		//判断并退出前面的`个零。如"00.0004"->"  0.0004"
		if('0' == str[0]){
			str[0]= ' ';
		}
	}
	else if( 5 == para_xxx.pt_pos_idx){
		//如"0.00004"
		//do nothing.
	}
	else{ 
		//do nothing.
	}	
	
	//从右到左（序号是5->0）找第一个' '，改为'-'。例如"   0.03" -->"  -0.03"。
	int i;
	for(i= 0; i< 6; i++){
		if(' ' != str[i])
			break;	//找到非' '。
	}
	
	if(0 == i){
		uartS("\n$err neg zeros");
		i= 1;
	}
	
	str[i-1]= '-';	//找到非' '，它前面位置即是'-'。
}



/*迟滞输出OUT1。
输入参数 sta:想要设置的状态。
说明：只有状态不变，并保持一段时间（暂定100ms），才输出此状态。若状态更改，重新计时。
*/
void out1(uint8_t sta)
{
	static uint32_t ts_pre= 0;
	static uint32_t ts= 0;
	static uint8_t sta_pre;
	
	ts= ts_get();
	
	if(sta_pre == sta){
		if(100< ts_del_o_n(ts_pre, ts)){
			ts_pre= ts;
			
			//输出当前值
			if(OUT_VALID == sta)
				OUT1_VALID;
			else
				OUT1_INVALID;
		}
	}
	else{
		ts_pre= ts;
		sta_pre= sta;
	}
}



/*迟滞输出OUT1。
输入参数 sta:想要设置的状态。
说明：只有状态不变，并保持一段时间（暂定100ms），才输出此状态。若状态更改，重新计时。
*/
void out2(uint8_t sta)
{
	static uint32_t ts_pre= 0;
	static uint32_t ts= 0;
	static uint8_t sta_pre;
	
	ts= ts_get();
	
	if(sta_pre == sta){
		if(100< ts_del_o_n(ts_pre, ts)){
			ts_pre= ts;
			
			//输出当前值
			if(OUT_VALID == sta)
				OUT2_VALID;
			else
				OUT2_INVALID;
		}
	}
	else{
		ts_pre= ts;
		sta_pre= sta;
	}
}

/************************ END OF FILE ************************/
